home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / prg_gen / euphor14.zip / SCHED.E < prev    next >
Text File  |  1995-02-10  |  4KB  |  122 lines

  1. -- sched.e
  2. -- Task Scheduler
  3.  
  4. -- This is perhaps the most interesting source file since it shows a
  5. -- simple technique of task scheduling that could be used in any action 
  6. -- game or simulation program. 
  7.  
  8. -- We have implemented a form of cooperative multitasking to manage 10 
  9. -- independent tasks. There is a task that moves the Euphoria, another task 
  10. -- that checks the keyboard for input, a task that makes enemy ships fire, 
  11. -- another that counts down the damage report, etc. The sequence "tcb" records
  12. -- the time at which each task wants to be activated next. When the time comes 
  13. -- to run a given task, the scheduler will return to the main program, telling
  14. -- it which task to run. When the task is finished it can tell the scheduler 
  15. -- when it would like to be activated next. 
  16.  
  17. -- For example, the task that moves the Euphoria will ask to be activated 
  18. -- again in 20 seconds if the Euphoria is moving at warp 1, or much less at 
  19. -- higher warps. The keyboard checking task is activated very frequently, but 
  20. -- usually returns quickly (no key pressed). 
  21.  
  22. -- Some tasks require very precise activation times to make things look 
  23. -- realistic, e.g. Euphoria moving at warp 5. Others do not, for example the 
  24. -- BASIC TRUCE/HOSTILE/CLOAKING task which is activated after a lengthy and 
  25. -- random amount of time. In recognition of this we have the "eat" (early 
  26. -- activation tolerance) variable. After choosing the next task to run, and 
  27. -- before entering into a delay loop to wait for the activation time to come,
  28. -- the scheduler will check the eat to see if it can activate the task a bit
  29. -- early. This will get this task out of the way a bit earlier and
  30. -- reduce the chance of a timing conflict with the next task.
  31.  
  32. -- Having said all this, the code is actually quite simple:
  33.  
  34. global constant HUGE_TIME = 1e30
  35. global constant INACTIVE = 0
  36.  
  37. global procedure sched(task t, positive_atom wait)
  38. -- schedule a task to be reactivated in wait seconds
  39.  
  40.     if wait = INACTIVE then
  41.     -- deactivate
  42.     tcb[t] = HUGE_TIME
  43.     else
  44.     -- activate in wait seconds from now
  45.     tcb[t] = time() + wait
  46.     end if
  47. end procedure
  48.  
  49.  
  50. global function next_task()
  51. -- choose the next task to be executed
  52.  
  53.     positive_atom mintime
  54.     task mintask
  55.  
  56.     -- find task with minimum time
  57.     mintask = 1
  58.     mintime = tcb[1]
  59.     for i = 2 to NTASKS do
  60.     if tcb[i] < mintime then
  61.         mintask = i
  62.         mintime = tcb[i]
  63.     end if
  64.     end for
  65.  
  66.     -- subtract it's early-activation tolerance
  67.     tcb[mintask] = tcb[mintask] - eat[mintask]
  68.  
  69.     -- wait until it is time to activate it
  70.     while time() < tcb[mintask] do
  71.     end while
  72.  
  73.     return mintask
  74. end function
  75.  
  76.  
  77. -- below we have some code that lets us perform short accurate time delays
  78. -- with better resolution than the usual 18.2 ticks per second under MS-DOS
  79. constant sample_interval = 1.0
  80. atom sample_count
  81.  
  82. type reasonable_delay(atom x)
  83.     return x > 0 and x < 30
  84. end type
  85.  
  86. global procedure init_delay()
  87. -- since time() does not have fine enough
  88. -- resolution for small delays, we see how many for-loop iterations
  89. -- we can complete over a small sample period
  90.  
  91.     atom t
  92.  
  93.     t = time() + sample_interval
  94.     for i = 1 to 999999999 do
  95.     if time() < t then
  96.     else
  97.         sample_count = i
  98.         exit
  99.     end if
  100.     end for
  101. end procedure
  102.  
  103. global procedure delay(reasonable_delay t)
  104. -- delay for t seconds
  105.     atom stop
  106.     if t > sample_interval then
  107.     -- time() should be precise enough
  108.     stop = time() + t
  109.     while time() < stop do
  110.     end while
  111.     else
  112.     -- loop a certain number of times
  113.     stop = time() + sample_interval
  114.     for i = 1 to floor(t / sample_interval * sample_count) do
  115.         if time() < stop then
  116.         else
  117.         end if
  118.     end for
  119.     end if
  120. end procedure
  121.  
  122.